home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / kernel / mach / sun4.md / machAsmDefs.h < prev    next >
C/C++ Source or Header  |  1992-12-18  |  14KB  |  459 lines

  1. /*
  2.  * machAsmDefs.h --
  3.  *
  4.  *     Machine-dependent macros.
  5.  *
  6.  * Copyright (C) 1985 Regents of the University of California
  7.  * All rights reserved.
  8.  *
  9.  *
  10.  * $Header: /cdrom/src/kernel/Cvsroot/kernel/mach/sun4.md/machAsmDefs.h,v 9.4 91/10/18 01:23:01 dlong Exp $ SPRITE (Berkeley)
  11.  */
  12.  
  13. #ifndef _MACHASMDEFS
  14. #define _MACHASMDEFS
  15.  
  16. #ifdef KERNEL
  17. #include <vmSunConst.h>
  18. #include <machConst.h>
  19. #else
  20. #include <kernel/vmSunConst.h>
  21. #include <kernel/machConst.h>
  22. #endif
  23.  
  24. /*
  25.  * Wait the 3 instructions necessary to allow a newly-written state register
  26.  * to settle.
  27.  */
  28. #define    MACH_WAIT_FOR_STATE_REGISTER()            \
  29.     nop;                        \
  30.     nop;                        \
  31.     nop
  32. /*
  33.  * Bump the invalid window forward one.  This is done by changing the
  34.  * invalid window mask.  We shift the invalid window bit left by 1,
  35.  * but modulo the number of implemented windows.
  36.  */
  37.  
  38. #define    MACH_ADVANCE_WIM(REG1, REG2)            \
  39.     mov    %wim, REG1;                \
  40.     sethi    %hi(_machWimShift), REG2;        \
  41.     ld    [REG2 + %lo(_machWimShift)], REG2;    \
  42.     sll    REG1, REG2, REG2;            \
  43.     srl    REG1, 0x1, REG1;            \
  44.     or    REG1, REG2, REG1;            \
  45.     mov    REG1, %wim;                \
  46.     MACH_WAIT_FOR_STATE_REGISTER()
  47.  
  48. /*
  49.  * Move the invalid window backwards one.  This is done by changing the
  50.  * invalid window mask.  We shift the invalid window bit right by 1,
  51.  * but modulo the number of implemented windows.
  52.  */
  53.  
  54. #define    MACH_RETREAT_WIM(REG1, REG2)            \
  55.     mov    %wim, REG1;                \
  56.     sethi    %hi(_machWimShift), REG2;        \
  57.     ld    [REG2 + %lo(_machWimShift)], REG2;    \
  58.     srl    REG1, REG2, REG2;            \
  59.     sll    REG1, 0x1, REG1;            \
  60.     or    REG1, REG2, REG1;            \
  61.     mov    REG1, %wim;                \
  62.     MACH_WAIT_FOR_STATE_REGISTER()
  63.  
  64. /*
  65.  * Set the window invalid mask to point to the current window.
  66.  */
  67. #define    MACH_SET_WIM_TO_CWP()                    \
  68.     mov    %psr, %VOL_TEMP1;                \
  69.     set    0x1, %VOL_TEMP2;                \
  70.     sll    %VOL_TEMP2, %VOL_TEMP1, %VOL_TEMP1;        \
  71.     mov    %VOL_TEMP1, %wim;                \
  72.     MACH_WAIT_FOR_STATE_REGISTER()
  73.  
  74. /*
  75.  * Test whether we're in an invalid window.  If we are in an invalid window,
  76.  * then the condition codes should indicate a not zero ("bne" instruction
  77.  * will branch).
  78.  */
  79. #define    MACH_INVALID_WINDOW_TEST()                \
  80.     mov    %psr, %VOL_TEMP1;                \
  81.     set    0x1, %VOL_TEMP2;                \
  82.     sll    %VOL_TEMP2, %VOL_TEMP1, %VOL_TEMP1;        \
  83.     mov    %wim, %VOL_TEMP2;                \
  84.     andcc    %VOL_TEMP1, %VOL_TEMP2, %g0
  85.  
  86. /*
  87.  * Test whether we're about to encounter a window underflow condition.
  88.  * We put current cwp into temp1.  We shift a one by that many bits.
  89.  * Then we shift it again, to "advance" the window by one.  We and it
  90.  * with the valid window bits to get it modulo the number of windows - 1.
  91.  * Then we compare it with current wim to see if they're the same.  If
  92.  * so, then we would get an underflow if we did a restore operation.
  93.  * If we are in an underflow situation, then the condition codes should
  94.  * indicate a not zero ("bne" instruction will branch).
  95.  */
  96.  
  97. #define    MACH_UNDERFLOW_TEST()                    \
  98.     mov    %psr, %VOL_TEMP1;                \
  99.     set    0x1, %VOL_TEMP2;                \
  100.     sll    %VOL_TEMP2, %VOL_TEMP1, %VOL_TEMP1;        \
  101.     sethi    %hi(_machWimShift), %VOL_TEMP2;            \
  102.     ld    [%VOL_TEMP2 + %lo(_machWimShift)], %VOL_TEMP2;    \
  103.     srl    %VOL_TEMP1, %VOL_TEMP2, %VOL_TEMP2;        \
  104.     sll    %VOL_TEMP1, 0x1, %VOL_TEMP1;            \
  105.     or    %VOL_TEMP1, %VOL_TEMP2, %VOL_TEMP1;        \
  106.     mov    %wim, %VOL_TEMP2;                \
  107.     andcc    %VOL_TEMP1, %VOL_TEMP2, %g0
  108.  
  109. /*
  110.  * The sequence we need to go through to restore the psr without restoring
  111.  * the old current window number.  We want to remain in our current window.
  112.  * 1) Get old psr.  2) Clear only its cwp bits.  3) Get current psr.
  113.  * 4) Grab only its cwp bits.  5) Stick the two together and put it in
  114.  * the psr reg.  6) Wait for the register to be valid.
  115.  */
  116. #define    MACH_RESTORE_PSR()                    \
  117.     mov    %CUR_PSR_REG, %VOL_TEMP2;            \
  118.     set     (~MACH_CWP_BITS), %VOL_TEMP1;            \
  119.     and     %VOL_TEMP2, %VOL_TEMP1, %VOL_TEMP2;        \
  120.     mov     %psr, %VOL_TEMP1;                \
  121.     and     %VOL_TEMP1, MACH_CWP_BITS, %VOL_TEMP1;        \
  122.     or      %VOL_TEMP2, %VOL_TEMP1, %VOL_TEMP2;        \
  123.     mov     %VOL_TEMP2, %psr;                \
  124.     MACH_WAIT_FOR_STATE_REGISTER()
  125.     
  126.  
  127. /*
  128.  * Save global registers.
  129.  * Store-doubles are faster and we do this from even register boundaries.
  130.  * For now, we only save the globals here, since the locals and ins will
  131.  * be saved on normal save-window operations.  Note that this means the
  132.  * stack pointer and MACH_GLOBALS_OFFSET must be double-word aligned.
  133.  */
  134. #define    MACH_SAVE_GLOBAL_STATE()                \
  135.     add    %sp, MACH_GLOBALS_OFFSET, %VOL_TEMP1;        \
  136.     std    %g0, [%VOL_TEMP1];                \
  137.     std    %g2, [%VOL_TEMP1 + 8];                \
  138.     std    %g4, [%VOL_TEMP1 + 16];                \
  139.     std    %g6, [%VOL_TEMP1 + 24]
  140.  
  141. /*
  142.  * Restore the global registers.  We do load doubles here for speed
  143.  * for even-register boundaries.  For now, we only restore the globals
  144.  * from here, since the locals and ins will be restored as part of the
  145.  * normal restore window operations.  Note that this means the stack pointer
  146.  * and MACH_GLOBALS_OFFSET must be double-word aligned.
  147.  */
  148. #define    MACH_RESTORE_GLOBAL_STATE()                \
  149.     add    %sp, MACH_GLOBALS_OFFSET, %VOL_TEMP1;        \
  150.     ldd    [%VOL_TEMP1], %g0;                \
  151.     ldd    [%VOL_TEMP1 + 8], %g2;                \
  152.     ldd    [%VOL_TEMP1 + 16], %g4;                \
  153.     ldd    [%VOL_TEMP1 + 24], %g6
  154.  
  155. /*
  156.  * Save r16 to r23 (locals) and r24 to r31 (ins) to 16 words at
  157.  * the top of this window's stack.
  158.  */
  159. #define    MACH_SAVE_WINDOW_TO_STACK()            \
  160.     std    %r16, [%sp];                \
  161.     std    %r18, [%sp + 8];            \
  162.     std    %r20, [%sp + 16];            \
  163.     std    %r22, [%sp + 24];            \
  164.     std    %r24, [%sp + 32];            \
  165.     std    %r26, [%sp + 40];            \
  166.     std    %r28, [%sp + 48];            \
  167.     std    %r30, [%sp + 56]
  168.  
  169. #define    MACH_RESTORE_WINDOW_FROM_STACK()        \
  170.     ldd    [%sp], %r16;                \
  171.     ldd    [%sp + 8], %r18;            \
  172.     ldd    [%sp + 16], %r20;            \
  173.     ldd    [%sp + 24], %r22;            \
  174.     ldd    [%sp + 32], %r24;            \
  175.     ldd    [%sp + 40], %r26;            \
  176.     ldd    [%sp + 48], %r28;            \
  177.     ldd    [%sp + 56], %r30
  178.  
  179. #define    MACH_SAVE_WINDOW_TO_BUFFER(reg1)        \
  180.     std    %r16, [reg1];                \
  181.     std    %r18, [reg1 + 8];            \
  182.     std    %r20, [reg1 + 16];            \
  183.     std    %r22, [reg1 + 24];            \
  184.     std    %r24, [reg1 + 32];            \
  185.     std    %r26, [reg1 + 40];            \
  186.     std    %r28, [reg1 + 48];            \
  187.     std    %r30, [reg1 + 56]
  188.  
  189.  
  190. /*
  191.  * Clear out the local and out registers for a new window to move into
  192.  * or a window we're moving out of.
  193.  * Outs: r8 to r15, locals: r16 to r23.
  194.  */
  195. #define    MACH_CLEAR_WINDOW()                \
  196.     clr    %r8;                    \
  197.     clr    %r9;                    \
  198.     clr    %r10;                    \
  199.     clr    %r11;                    \
  200.     clr    %r12;                    \
  201.     clr    %r13;                    \
  202.     clr    %r14;                    \
  203.     clr    %r15;                    \
  204.     clr    %r16;                    \
  205.     clr    %r17;                    \
  206.     clr    %r18;                    \
  207.     clr    %r19;                    \
  208.     clr    %r20;                    \
  209.     clr    %r21;                    \
  210.     clr    %r22;                    \
  211.     clr    %r23
  212.  
  213. /*
  214.  * Enabling and disabling traps.
  215.  */
  216. #define    MACH_ENABLE_TRAPS(useReg)            \
  217.     mov    %psr, useReg;                \
  218.     or    useReg, MACH_ENABLE_TRAP_BIT, useReg;    \
  219.     mov    useReg, %psr;                \
  220.     MACH_WAIT_FOR_STATE_REGISTER()
  221.  
  222. /*
  223.  * Should I use xor here and MACH_ENABLE_TRAP_BIT?
  224.  */
  225. #define    MACH_DISABLE_TRAPS(useReg1, useReg2)        \
  226.     mov    %psr, useReg1;                \
  227.     set    MACH_DISABLE_TRAP_BIT, useReg2;        \
  228.     and    useReg1, useReg2, useReg1;        \
  229.     mov    useReg1, %psr;                \
  230.     MACH_WAIT_FOR_STATE_REGISTER()
  231.  
  232. /*
  233.  * Equivalents to C macros for enabling and disabling interrupts.
  234.  * They aren't quite equivalent, since they don't do panic's on negative
  235.  * disable counts.  These macros should really only be used for debugging,
  236.  * in any case.
  237.  */
  238. #define    DISABLE_INTR_ASM(reg1, reg2, NoDisableLabel)    \
  239.     set    _mach_AtInterruptLevel, reg1;    \
  240.     ld    [reg1], reg1;            \
  241.     tst    reg1;                \
  242.     bne    NoDisableLabel;            \
  243.     nop;                    \
  244.     mov    %psr, reg1;            \
  245.     set    MACH_DISABLE_INTR, reg2;    \
  246.     or    reg1, reg2, reg1;        \
  247.     mov    reg1, %psr;            \
  248.     MACH_WAIT_FOR_STATE_REGISTER();        \
  249.     set    _mach_NumDisableIntrsPtr, reg1;    \
  250.     ld    [reg1], reg2;            \
  251.     add    reg2, 0x1, reg2;        \
  252.     st    reg2, [reg1];            \
  253. NoDisableLabel:
  254.  
  255. #define    ENABLE_INTR_ASM(reg1, reg2, NoEnableLabel)    \
  256.     set    _mach_AtInterruptLevel, reg1;    \
  257.     ld    [reg1], reg1;            \
  258.     tst    reg1;                \
  259.     bne    NoEnableLabel;            \
  260.     nop;                    \
  261.     set    _mach_NumDisableIntrsPtr, reg1;    \
  262.     ld    [reg1], reg2;            \
  263.     sub    reg2, 0x1, reg2;        \
  264.     st    reg2, [reg1];            \
  265.     tst    reg2;                \
  266.     bne    NoEnableLabel;            \
  267.     nop;                    \
  268.     mov    %psr, reg1;            \
  269.     set    MACH_ENABLE_INTR, reg2;        \
  270.     and    reg1, reg2, reg1;        \
  271.     mov    reg1, %psr;            \
  272.     MACH_WAIT_FOR_STATE_REGISTER();        \
  273. NoEnableLabel:
  274.  
  275. /*
  276.  * Enable interrupts and keep traps enabled.
  277.  * Uses given register.
  278.  */
  279. #define    QUICK_ENABLE_INTR(reg)                \
  280.     mov    %psr, reg;                \
  281.     andn    reg, MACH_DISABLE_INTR, reg;        \
  282.     mov    reg, %psr;                \
  283.     MACH_WAIT_FOR_STATE_REGISTER()
  284.  
  285. /*
  286.  * Disable interrupts and keep traps enabled.
  287.  * Uses given register.
  288.  */
  289. #define    QUICK_DISABLE_INTR(reg)                \
  290.     mov    %psr, reg;                \
  291.     or    reg, MACH_DISABLE_INTR, reg;        \
  292.     mov    reg, %psr;                \
  293.     MACH_WAIT_FOR_STATE_REGISTER()
  294.  
  295. /*
  296.  * Set interrupts to a particular value.  This is useful for a routine that
  297.  * just wants to save the value, change it, and then reset it without worrying
  298.  * about whether this turns interrupts on or off.
  299.  */
  300. #define    SET_INTRS_TO(regValue, useReg1, useReg2)        \
  301.     mov    %psr, useReg1;                    \
  302.     set    MACH_ENABLE_INTR, useReg2;            \
  303.     and    useReg1, useReg2, useReg1;            \
  304.     set    MACH_DISABLE_INTR, useReg2;            \
  305.     and    regValue, useReg2, useReg2;            \
  306.     or    useReg1, useReg2, useReg1;            \
  307.     mov    useReg1, %psr;                    \
  308.     MACH_WAIT_FOR_STATE_REGISTER()
  309.  
  310. /*
  311.  * Run at high priority: supervisor mode, interrupts disabled, traps enabled.
  312.  * This must be done in 2 steps - 1) leaving traps off, if they were off,
  313.  * set new interrupt level.  2) Enable traps.  This keeps us from getting
  314.  * an interrupt at the old level rather than the new right after enabling
  315.  * traps.
  316.  */
  317. #define    MACH_SR_HIGHPRIO()                    \
  318.     mov    %psr, %VOL_TEMP1;                \
  319.     set    (MACH_DISABLE_INTR | MACH_SUPER_BIT), %VOL_TEMP2;    \
  320.     or    %VOL_TEMP1, %VOL_TEMP2, %VOL_TEMP1;        \
  321.     mov    %VOL_TEMP1, %psr;                \
  322.     or    %VOL_TEMP1, MACH_ENABLE_TRAP_BIT, %VOL_TEMP1;    \
  323.     mov    %VOL_TEMP1, %psr;                \
  324.     MACH_WAIT_FOR_STATE_REGISTER()
  325.  
  326. /*
  327.  * Run at low supervisor priority: supervisor mode, interrupts enabled, traps
  328.  * enabled.  As described above for MACH_SR_HIGHPRIO, we must do this in
  329.  * 2 steps.
  330.  */
  331. #define    MACH_SR_LOWPRIO()                    \
  332.     mov    %psr, %VOL_TEMP1;                \
  333.     set    MACH_SUPER_BIT, %VOL_TEMP2;            \
  334.     or    %VOL_TEMP1, %VOL_TEMP2, %VOL_TEMP1;        \
  335.     set    MACH_ENABLE_INTR, %VOL_TEMP2;            \
  336.     and    %VOL_TEMP1, %VOL_TEMP2, %VOL_TEMP1;        \
  337.     mov    %VOL_TEMP1, %psr;                \
  338.     or    %VOL_TEMP1, MACH_ENABLE_TRAP_BIT, %VOL_TEMP2;    \
  339.     mov    %VOL_TEMP1, %psr;                \
  340.     MACH_WAIT_FOR_STATE_REGISTER()
  341. /*
  342.  * Run at user priority: user mode, traps on.
  343.  */
  344. #define    MACH_SR_USERPRIO()                    \
  345.     mov    %psr, %VOL_TEMP1;                \
  346.     set    MACH_ENABLE_TRAP_BIT, %VOL_TEMP2;        \
  347.     or    %VOL_TEMP1, %VOL_TEMP2, %VOL_TEMP1;        \
  348.     set    (~MACH_SUPER_BIT), %VOL_TEMP2;            \
  349.     and    %VOL_TEMP1, %VOL_TEMP2, %VOL_TEMP1;        \
  350.     mov    %VOL_TEMP1, %psr;                \
  351.     MACH_WAIT_FOR_STATE_REGISTER()
  352.  
  353.  
  354. /*
  355.  * For sticking debug info into a buffer.  After each value, stamp a special
  356.  * mark, which gets overwritten by the next value, so we always know where
  357.  * the end of the list is.
  358.  */
  359. #define    MACH_DEBUG_BUF(reg1, reg2, DebugLabel, stuff)    \
  360.     set    _debugCounter, reg1;         \
  361.     ld    [reg1], reg1;            \
  362.     sll    reg1, 2, reg1;            \
  363.     set    _debugSpace, reg2;        \
  364.     add    reg2, reg1, reg2;        \
  365.     st    stuff, [reg2];            \
  366.     set    _debugCounter, reg1;        \
  367.     ld    [reg1], reg1;            \
  368.     add    reg1, 1, reg1;            \
  369.     set    500, reg2;            \
  370.     subcc    reg2, reg1, %g0;        \
  371.     bgu    DebugLabel;            \
  372.     nop;                    \
  373.     clr    reg1;                \
  374. DebugLabel:                    \
  375.     set    _debugCounter, reg2;        \
  376.     st    reg1, [reg2];            \
  377.     sll    reg1, 2, reg1;            \
  378.     set    _debugSpace, reg2;        \
  379.     add    reg2, reg1, reg2;        \
  380.     set    0x11100111, reg1;        \
  381.     st    reg1, [reg2]
  382.  
  383. #define    MACH_DEBUG_ONCE(reg1, reg2, NoMoreLabel, DebugLabel, stuff, a_num)\
  384.     set    _debugCounter, reg1;        \
  385.     ld    [reg1], reg1;            \
  386.     cmp    reg1, a_num;            \
  387.     bg    NoMoreLabel;            \
  388.     nop;                    \
  389.     MACH_DEBUG_BUF(reg1, reg2, DebugLabel, stuff);    \
  390. NoMoreLabel:                    \
  391.     nop
  392.  
  393. /*
  394.  * This is the equivalent to a call to VmmachGetPage followed by a test on
  395.  * the returned pte to see if it is resident and user readable and writable.
  396.  * This is used where a call to the vm code won't work since output registers
  397.  * aren't available.  This sets the condition codes so that 0 is returned
  398.  * if the address is resident and not protected and not zero is returned if
  399.  * a fault would occur.
  400.  */
  401. #define    MACH_CHECK_FOR_FAULT(checkReg, reg1)    \
  402.     set    VMMACH_PAGE_MAP_MASK, reg1;        \
  403.     and    checkReg, reg1, reg1;            \
  404.     lda    [reg1] VMMACH_PAGE_MAP_SPACE, reg1;    \
  405.     srl    reg1, VMMACH_PAGE_PROT_SHIFT, reg1;    \
  406.     cmp    reg1, VMMACH_PTE_OKAY_VALUE
  407.  
  408. /*
  409.  * This is similar to the above macro, except that it is intended for checking
  410.  * stack pointers to see if a restore of a window would page fault.  We check
  411.  * the value of the stack pointer, and the offset of the window size.
  412.  */
  413. #define MACH_CHECK_STACK_FAULT(checkReg, reg1, ansReg, reg2, TestAgainLabel, LastOKLabel)    \
  414.     clr    ansReg;                    \
  415.     set    VMMACH_PAGE_MAP_MASK, reg1;        \
  416.     and    checkReg, reg1, reg1;            \
  417.     lda    [reg1] VMMACH_PAGE_MAP_SPACE, reg1;    \
  418.     srl    reg1, VMMACH_PAGE_PROT_SHIFT, reg1;    \
  419.     cmp    reg1, VMMACH_PTE_OKAY_VALUE;        \
  420.     be    TestAgainLabel;                \
  421.     nop;                        \
  422.     set    0x2, ansReg;                \
  423. TestAgainLabel:                        \
  424.     set    VMMACH_PAGE_MAP_MASK, reg1;        \
  425.     add    checkReg, (MACH_SAVED_WINDOW_SIZE - 4), reg2;    \
  426.     and    reg2, reg1, reg1;            \
  427.     lda    [reg1] VMMACH_PAGE_MAP_SPACE, reg1;    \
  428.     srl    reg1, VMMACH_PAGE_PROT_SHIFT, reg1;    \
  429.     cmp    reg1, VMMACH_PTE_OKAY_VALUE;        \
  430.     be    LastOKLabel;                \
  431.     nop;                        \
  432.     or    ansReg, 0x4, ansReg;            \
  433. LastOKLabel:                        \
  434.     tst    ansReg
  435.     
  436.     
  437.  
  438.  
  439. /*
  440.  * Get a ptr to the pcb structure of the current process.
  441.  * Return this in reg1
  442.  */
  443. #define    MACH_GET_CUR_PROC_PTR(reg1)            \
  444.     set    _proc_RunningProcesses, reg1;        \
  445.     ld    [reg1], reg1;                \
  446.     ld    [reg1], reg1
  447.  
  448. /*
  449.  * Get a ptr to the Mach_State struct of the current process.  Put it in reg1.
  450.  */
  451. #define    MACH_GET_CUR_STATE_PTR(reg1, reg2)        \
  452.     MACH_GET_CUR_PROC_PTR(reg1);            \
  453.         set     _machStatePtrOffset, reg2;        \
  454.         ld      [reg2], reg2;                \
  455.         add     reg1, reg2, reg1;            \
  456.         ld      [reg1], reg1
  457.  
  458. #endif /* _MACHASMDEFS */
  459.